<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>OpenEarthEngine-Workbench</title>
	<script src="ol.js"></script>
	<link rel="stylesheet" href="ol.css" />
	<script type="text/javascript" src="jquery.js"></script>
	<script src="jquery-ui.js"></script>
	<link href="jquery-ui.css" rel="stylesheet">
	<script type="text/javascript" src="js/jquery.ztree.all.min.js"></script>
	<link rel="stylesheet" href="css/zTreeStyle/zTreeStyle.css" type="text/css">
	<script src="ace/src-min/ace.js" type="text/javascript" charset="utf-8"></script>
	<style type="text/css" media="screen">
		/* #editor {
			position: absolute;
			top: 0;
			right: 0;
			height: 196px;
			left: 0;
		} */
		#editor {
			height: 190px;
		}

		#editorStyle {
			height: 190px;
		}

		#editorLogs {
			height: 210px;
		}


		button {
			padding: 0px;
			padding-left: 10px;
			padding-right: 10px;
			margin-right: 10px;
			border-width: 1px;
			height: 18px;
			font-size: 16px;
		}
	</style>
</head>

<body>
	<!-- Row 1-->
	<div>
		<div style="width:250px;height:220px;float:left;overflow:auto;">
			<ul id="tree-pdt" class="ztree" style="width:240px; overflow:auto;"></ul>
		</div>
		<div style="width:250px;height:220px;float:left;overflow:auto;">
			<ul id="tree-roi" class="ztree" style="width:240px; overflow:auto;"></ul>
		</div>
		<div style="width:250px;height:220px;float:left;overflow:auto;">
			<ul id="tree-style" class="ztree" style="width:240px; overflow:auto;"></ul>
		</div>
		<div style="width:250px;height:220px;float:left;overflow:auto;">
			<ul id="tree-js" class="ztree" style="width:240px; overflow:auto;"></ul>
		</div>

		<div style="position:relative;width:800px;height:240px;float:left;overflow:auto;">
			<div id="tabs"
				style="position:relative;width:100%;height:240px;border-width: 0px;padding: 0px;overflow: hidden;">
				<ul style="height:20px;padding: 0px;padding-bottom: 2px;">
					<li style="height:18px;padding: 0px;">
						<a id="scriptTabName" href="#tabs-1"
							style="padding-left:8px; padding-right:8px;padding-top: 0px;padding-bottom: 0px;">no
							script</a>
					</li>
					<li style="height:18px;padding: 0px;">
						<a href="#tabs-2" id="styleTabName"
							style="padding-left:8px; padding-right:8px;padding-top: 0px;padding-bottom: 0px;">no
							style</a>
					</li>
					<li style="height:18px;padding: 0px;">
						<a href="#tabs-3" id="logs"
							style="padding-left:8px; padding-right:8px;padding-top: 0px;padding-bottom: 0px;">logs</a>
					</li>
				</ul>
				<div id="tabs-1" style="position:relative;width:100%;height:240px;padding: 0px;overflow: hidden;">
					<div id="editor">function main() { return null; }</div>
					<div style="margin-top: 2px;">
						<button id="btnSaveJs" onclick="onSaveJsClick()">Save</button>
						<button id="btnSaveAsJs" onclick="onSaveAsJsClick()">Save as</button>
						<button id="btnRunJs" onclick="onRunJsClick()">Run</button>

					</div>
				</div>
				<div id="tabs-2" style="position:relative;width:100%;height:240px;padding: 0px;overflow: hidden;">
					<div id="editorStyle">{}</div>
					<div style="margin-top: 2px;">
						<button id="btnSaveStyle" onclick="onSaveStyleClick()">Save</button>
						<button id="btnSaveAsStyle" onclick="onSaveAsStyleClick()">Save as</button>
					</div>
				</div>
				<div id="tabs-3" style="position:relative;width:100%;height:240px;padding: 0px;overflow: hidden;">
					<div id="editorLogs"></div>
				</div>
			</div>

		</div>

	</div>

	<!-- ROW 2 -->
	<div style="clear:both;">
		<!-- Col 1 -->
		<div style="width: 100%;">
			<div>
				<button onclick="startFreeDraw()">开始绘制感兴趣区</button>
				<button onclick="stopFreeDraw()">结束绘制</button>
				<button onclick="clearFreeDraw()">清除绘制</button>
				<button onclick="saveFreeDraw()">保存绘制</button>
				<span style="font-size: 14px;">日期时间(dt):</span><input id="dt" type="text" name="dt"
					value="20240101000000" size="15" />
				<span style="font-size: 14px;">交互参数(sdui):</span><input id="sdui" type="text" name="sdui" value="null"
					size="100" />
				<span style="font-size: 14px;">绘制样式(styleid):</span><input id="styleid" type="text" name="styleid"
					value="null" size="15" />
			</div>
			<div id="map" style="width:100%;height:660px;border:1px solid black;"></div>
		</div>
		<span style="font-size: 14px;float: right;">version: v1.2.0.0</span>
		<!-- v1.2.x add logs -->
	</div>
	<script>
		// 当前脚本名称
		var g_currentJsName = "";
		var g_currentStyleName = "";
		// 默认文件名
		var g_defaultJsName = "temp.js";
		var g_defaultRoiName = "temp-roi.geojson";
		var g_defaultStyleName = "temp-style.json";
		//服务器API跟地址
		const server_api_root = "http://192.168.56.101:8881";


		//trees -----------------------------------------------
		var uiTreePtd = null;
		var uiTreeRoi = null;
		var uiTreeScripts = null;
		var uiTreeStyles = null;
		var setting = {
			view: {
				dblClickExpand: false,
				showLine: true,
				selectedMulti: false
			},
			data: {
				simpleData: {
					enable: true,
					idKey: "id",
					pIdKey: "pId",
					rootPId: ""
				}
			},
			callback: {
				// beforeClick: function (treeId, treeNode) {
				// 	console.log(treeId + "-" + treeNode.fullname);
				// },
				onDblClick: function (ev, treeId, node) {
					if (treeId === 'tree-js') {
						loadOneScript(node.fullname);
					} else if (treeId === 'tree-style') {
						loadOneStyle(node.fullname);
					}
				}
			}
		};

		var zNodes = [
			{ id: 1, pId: 0, name: "Products(TILED)", open: false },
			{ id: 2, pId: 0, name: "Products(COG)", open: false },
		];

		var roiNodes = [
			{ id: 1, pId: 0, name: "ROIs", open: false },
		];

		var jsNodes = [
			{ id: 1, pId: 0, name: "Scripts", open: false },
		];

		var styleNodes = [
			{ id: 1, pId: 0, name: "Styles", open: false },
		];

		//更新当前脚本文件名
		function updateCurrentJsName() {
			$("#scriptTabName").html(g_currentJsName);
		}

		//更新当前绘制方案文件名
		function updateCurrentStyleName() {
			$("#styleTabName").html(g_currentStyleName);
		}

		//加载脚本并显示在 editor 里面
		function loadOneScript(jsname) {
			$.get(server_api_root + "/script?jsname=" + jsname, function (data) {
				editor.setValue(data);
				g_currentJsName = jsname;
				updateCurrentJsName();
			});
		}

		// 加载绘制样式，并显示在 editorStyle 里面
		function loadOneStyle(jsname) {
			$.get(server_api_root + "/style?name=" + jsname, function (data) {
				editorStyle.setValue(data);
				g_currentStyleName = jsname;
				updateCurrentStyleName();
			});
		}

		//使用 zNodes 对象更新产品树
		function updateProductTrees() {
			uiTreePtd = $("#tree-pdt");
			uiTreePtd = $.fn.zTree.init(uiTreePtd, setting, zNodes);
		}

		//使用 roiNodes 对象更新ROI树
		function updateROIsTrees() {
			uiTreeRoi = $("#tree-roi");
			uiTreeRoi = $.fn.zTree.init(uiTreeRoi, setting, roiNodes);
		}

		//更新 Styles 树
		function updateStylesTrees() {
			uiTreeStyles = $("#tree-style");
			uiTreeStyles = $.fn.zTree.init(uiTreeStyles, setting, styleNodes);
		}

		//使用 jsNodes 对象更新脚本树
		function updateScriptsTrees() {
			uiTreeScripts = $("#tree-js");
			uiTreeScripts = $.fn.zTree.init(uiTreeScripts, setting, jsNodes);
		}

		//获取每个产品下面的日期时间
		function loadOneProductDtArr(pdtinfo, parentId) {
			$.get(server_api_root + "/productdtarr?dsname=" + pdtinfo.pdtname, function (data) {
				let uuid1 = parentId + 1;
				if (data.length > 0) {
					for (let dt1 of data) {
						uuid1++;
						zNodes.push({ id: uuid1, pId: parentId, name: dt1, fullname: pdtinfo.pdtname + '/' + dt1, open: false });
					}
				} else {
					uuid1++;
					zNodes.push({ id: uuid1, pId: parentId, name: "empty", fullname: "empty", open: false });
				}
				updateProductTrees();
			});
		}


		//------------ global settings ----------------------------------


		//获取全部产品信息，并更新产品树
		function updateProductInfos() {
			//初始化产品树跟节点
			zNodes = [
				{ id: 1, pId: 0, name: "Products(TILED)", open: false },
				{ id: 2, pId: 0, name: "Products(COG)", open: false },
			];
			let uuid = 10000;
			$.get(server_api_root + "/productinfo", function (data) {
				for (let pdt of data) {
					uuid += 10000;
					console.log(pdt);
					if (pdt.hTableName === "COG") {
						zNodes.push({ id: uuid, pId: 2, name: pdt.pdtname, fullname: pdt.pdtname, open: false });
						loadOneProductDtArr(pdt, uuid);
					} else {
						zNodes.push({ id: uuid, pId: 1, name: pdt.pdtname, fullname: pdt.pdtname, open: false });
						loadOneProductDtArr(pdt, uuid);
					}
				}
			});
		}


		//获取全部绘制样式数据
		function updateStyles() {
			//初始化产品树跟节点
			styleNodes = [
				{ id: 1, pId: 0, name: "Styles", open: false },
			];
			$.get(server_api_root + "/styles", function (data) {
				var uuid = 10000;
				for (let ss1 of data) {
					uuid += 1;
					styleNodes.push({ id: uuid, pId: 1, name: ss1, fullname: ss1, open: false });
				}
				updateStylesTrees();
			});
		}


		//获取全部ROI，更新树
		function updateRois() {
			roiNodes = [
				{ id: 1, pId: 0, name: "ROIs", open: false },
			];
			$.get(server_api_root + "/rois", function (data) {
				var uuid = 10000;
				for (let roi1 of data) {
					uuid += 1;
					roiNodes.push({ id: uuid, pId: 1, name: roi1, fullname: roi1, open: false });
				}
				updateROIsTrees();
			});
		}


		//获取全部脚本，更新树
		function updateScripts() {
			console.log("call updateScripts");
			jsNodes = [
				{ id: 1, pId: 0, name: "Scripts", open: false },
			];
			$.get(server_api_root + "/scripts", function (data) {
				console.log("scripts");
				console.log(data);
				var uuid = 10000;
				for (let s1 of data) {
					uuid += 1;
					jsNodes.push({ id: uuid, pId: 1, name: s1, fullname: s1, open: false });
				}
				updateScriptsTrees();
			});
		}


		//html加载后执行
		$(document).ready(function () {
			updateProductInfos();
			updateRois();
			updateScripts();
			updateStyles();
			//updateStylesTrees();
			// uiTreeRoi = $("#tree-roi");
			// uiTreeRoi = $.fn.zTree.init(uiTreeRoi, setting, roiNodes);
			// uiTreeScripts = $("#tree-js");
			// uiTreeScripts = $.fn.zTree.init(uiTreeScripts, setting, jsNodes);

		});





		//------------------
		//editor
		var editor = ace.edit("editor");
		editor.session.setMode("ace/mode/javascript");
		var editorStyle = ace.edit("editorStyle");
		editorStyle.session.setMode("ace/mode/json");
		var editorLogs = ace.edit("editorLogs");
		editorLogs.session.setMode("ace/mode/text");

		// 保存当前脚本
		function onSaveJsClick() {
			let codetext = editor.getValue();
			let fname = g_currentJsName;
			if (fname !== "") {
				let obj = {};
				obj["fname"] = fname;
				obj["text"] = codetext;
				$.post(server_api_root + "/savejs", obj, function (data) {
					console.log(data);
				});
			}
		}

		// 另存脚本
		function onSaveAsJsClick() {
			let codetext = editor.getValue();
			let outFilename = prompt("脚本文件名(重名覆盖)", g_defaultJsName);
			if (outFilename === null) return;
			if (outFilename !== "") {
				g_defaultJsName = outFilename;
				g_currentJsName = outFilename;
				let fname = g_currentJsName;
				if (fname !== "") {
					let obj = {};
					obj["fname"] = fname;
					obj["text"] = codetext;
					$.post(server_api_root + "/savejs", obj,
						function (data) {
							updateCurrentJsName();
							updateScripts();
						});
				}
			}
		}

		//保存一个渲染方案
		function onSaveStyleClick() {
			let codetext = editorStyle.getValue();
			let fname = g_currentStyleName;
			if (fname !== "") {
				let obj = {};
				obj["fname"] = fname;
				obj["text"] = codetext;
				$.post(server_api_root + "/savestyle", obj, function (data) {
					console.log(data);
				});
			}
		}

		//另存一个渲染方案
		function onSaveAsStyleClick() {
			let codetext = editorStyle.getValue();
			let outFilename = prompt("绘制样式文件名(重名覆盖)", g_defaultStyleName);
			if (outFilename === null) return;
			if (outFilename !== "") {
				g_defaultStyleName = outFilename;
				g_currentStyleName = outFilename;
				let fname = g_currentStyleName;
				if (fname !== "") {
					let obj = {};
					obj["fname"] = fname;
					obj["text"] = codetext;
					$.post(server_api_root + "/savestyle", obj,
						function (data) {
							updateCurrentStyleName();
							updateStyles();
						});
				}
			}
		}

		//加载脚本运行日志并显示在logs里面。
		function loadAndDisplayLogs(jsname, datetime, sdui, styleid) {
			$.get(server_api_root + "/logs?name=" + jsname + "&datetime=" + datetime + "&sdui=" + sdui + "&styleid=" + styleid, function (data) {
				let oldText = editorLogs.getValue();
				editorLogs.setValue(oldText+data);
			});
		}


		// DataTile 2024/9/4
		const canvas = document.createElement('canvas');
		canvas.width = 256;
		canvas.height = 256;
		const context = canvas.getContext('2d', {willReadFrequently: true});
		context.strokeStyle = 'white';
		context.textAlign = 'center';
		context.font = '24px sans-serif';
		const loaderFunction=function(z,x,y) {
			const url1= server_api_root + '/' + jsName1 + '/rawdata/' + "?layer="+jsName1+"&style=default&tilematrixset=ms_14&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image%2Fpng&TileMatrix="+z+"&TileCol="+x+"&TileRow="+y+"&datetime="+dtstr+"&sdui="+sduistr+"&styleid="+stylename;
			console.log( String(z) + ',' + x + ','+y);
			return fetch(url1)
				.then((response)=>response.arrayBuffer())
				.then((arrBuff)=>{
					const byteDataArray = new Uint8Array(arrBuff);
					const size=256;
					const lineHeight=30;
					const half = size / 2;
					context.clearRect(0, 0, size,size );
					context.fillStyle = 'rgba(100, 100, 100, 0.5)';
					context.fillRect(0, 0, size, size);
					context.fillStyle = 'black';
					context.fillText(`z: ${byteDataArray[0]}`, half, half - lineHeight);
					context.fillText(`x: ${x}`, half, half);
					context.fillText(`y: ${y}`, half, half + lineHeight);
					context.strokeRect(0, 0, size, size);
					console.log( String(z) + ',' + x + ','+y);
					return context.getImageData(0, 0, size, size).data;
				}) ;					
		}
			

		// 2024/9/4 .






		//点击脚本运行
		function onRunJsClick() {
			if (g_currentJsName === "") {
				window.alert("当前脚本名为空");
				return;
			}

			let jsName1 = g_currentJsName.replace(".js", "");
			let dtstr = $("#dt").val();
			let sduistr = $("#sdui").val();
			let stylename = $("#styleid").val();
			if (stylename === "") stylename = "null";

			const wmtsSource = new ol.source.WMTS({
				attributions: '1',
				url: server_api_root + '/' + jsName1 + '/wmts/',
				layer: jsName1,
				matrixSet: 'ms_14',
				format: 'image/png',
				projection: projection,
				tileGrid: new ol.tilegrid.WMTS({
					origin: ol.extent.getTopLeft(projectionExtent),
					resolutions: resolutions,
					matrixIds: matrixIds,
				}),
				style: 'default',
				wrapX: false,
				dimensions: {
					datetime: dtstr,
					sdui: sduistr,
					styleid: stylename
				}
			});
			//let dimensions = { sdui: JSON.stringify(sdui) };// pe.extraData.datetime
			g_scriptLayer.setSource(wmtsSource);
			//function loadAndDisplayLogs(jsname, datetime, sdui, styleid) 
			loadAndDisplayLogs(g_currentJsName, dtstr, sduistr, stylename);

			// DataTile 2024/9/4
			const rawdataSource = new ol.source.DataTile({
				attributions: 'rawdata',
				projection: projection,
				tileGrid: new ol.tilegrid.WMTS({
					origin: ol.extent.getTopLeft(projectionExtent),
					resolutions: resolutions,
					matrixIds: matrixIds,
				}),
				style: 'default',
				wrapX: false,
				loader:function(z,x,y) {
					const url1= server_api_root + '/' + jsName1 + '/rawdata/' + "?layer="+jsName1+"&style=default&tilematrixset=ms_14&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image%2Fpng&TileMatrix="+z+"&TileCol="+x+"&TileRow="+y+"&datetime="+dtstr+"&sdui="+sduistr+"&styleid="+stylename;
					console.log( String(z) + ',' + x + ','+y);
					return fetch(url1)
						.then((response)=>response.arrayBuffer())
						.then((arrBuff)=>{
							const byteDataArray = new Uint8Array(arrBuff);
							const size=256;
							const lineHeight=30;
							const half = size / 2;
							context.clearRect(0, 0, size,size );
							context.fillStyle = 'rgba(100, 100, 100, 0.5)';
							context.fillRect(0, 0, size, size);
							context.fillStyle = 'black';
							context.fillText(`z: ${byteDataArray[0]}`, half, half - lineHeight);
							context.fillText(`x: ${x}`, half, half);
							context.fillText(`y: ${y}`, half, half + lineHeight);
							context.strokeRect(0, 0, size, size);
							console.log( String(z) + ',' + x + ','+y);
							return context.getImageData(0, 0, size, size).data;
						}) ;
				}
			});
			g_scriptRawdataLayer.setSource(rawdataSource);
			// 2024/9/4 .

		}



		//---------- OpenLayer -------------------------------
		const projection = ol.proj.get('EPSG:4326');
		const projectionExtent = projection.getExtent();
		const size = ol.extent.getWidth(projectionExtent) / 256;
		const resolutions = new Array(19);
		const matrixIds = new Array(19);
		for (let z = 0; z < 19; ++z) {
			// generate resolutions and matrixIds arrays for this WMTS
			resolutions[z] = size / Math.pow(2, z);
			matrixIds[z] = z;
		}


		//background lines
		const bgstyle = function () {
			return new ol.style.Style({
				stroke: new ol.style.Stroke({
					color: '#BABABA',
					width: 1,
				}),
			});
		}

		//图层定义
		var g_freedrawInteraction = null;
		var g_freedrawSource = new ol.source.Vector({ wrapX: false });
		var g_freedrawLayer = new ol.layer.Vector({ format: new ol.format.GeoJSON({ dataProjection: 'EPSG:4326' }), source: g_freedrawSource });
		const bgsource = new ol.source.Vector({ url: server_api_root + "/bglines", format: new ol.format.GeoJSON() });
		const bglayer = new ol.layer.Vector({ source: bgsource, style: bgstyle });

		//script layer
		var g_scriptLayer = new ol.layer.Tile({ maxZoom: 14, source: null, });
		var g_scriptRawdataLayer = new ol.layer.WebGLTile({ maxZoom: 14, source: null, });

		//初始化OpenLayer
		const map = new ol.Map({
			target: 'map',
			layers: [
				g_scriptRawdataLayer,
				g_scriptLayer,
				bglayer,
				g_freedrawLayer
			],
			view: new ol.View({
				projection: 'EPSG:4326',
				center: [0, 0],
				zoom: 1,
			}),
		});
		function onUpdateSdui() {
			console.log("onUpdateSdui");
			let bufferwid = document.getElementById("bufferwid").value;
			let wkt = document.getElementById("wkt").value;
			let sdui = { bufferwid: bufferwid, wkt: wkt };
			console.log(sdui);
			let dimensions = { sdui: JSON.stringify(sdui) };
			wmtsSource.updateDimensions(dimensions);
		}

		//自由绘制
		function startFreeDraw() {
			g_freedrawInteraction = new ol.interaction.Draw({
				source: g_freedrawSource,
				type: "Polygon",
				freehand: true,
			});
			map.addInteraction(g_freedrawInteraction);
		}

		//结束绘制
		function stopFreeDraw() {
			if (g_freedrawInteraction !== null) {
				map.removeInteraction(g_freedrawInteraction);
				g_freedrawInteraction = null;
			}
		}

		//清除绘制内容
		function clearFreeDraw() {
			if (g_freedrawInteraction !== null) {
				map.removeInteraction(g_freedrawInteraction);
				g_freedrawInteraction = null;
			}
			g_freedrawSource.clear();
		}

		//保持绘制geojson到后台
		function saveFreeDraw() {
			if (g_freedrawInteraction !== null) {
				map.removeInteraction(g_freedrawInteraction);
				g_freedrawInteraction = null;
			}

			if (typeof g_freedrawSource.features !== 'undefined' ||
				g_freedrawSource.getFeatures().length > 0) {
				let outFilename = prompt("感兴趣区文件名(重名覆盖)", g_defaultRoiName);
				if (outFilename === null) return;
				if (outFilename !== "") {
					g_defaultRoiName = outFilename;
					let features = g_freedrawSource.getFeatures();
					let parser = new ol.format.GeoJSON();
					let geojsonText = parser.writeFeatures(features, { featureProjection: 'EPSG:4326' });
					let obj = {};
					obj["fname"] = outFilename;
					obj["geojson"] = geojsonText;
					$.post(server_api_root + "/saveroi", obj, function (data) {
						updateRois();
					}
					);
				}
			}
		}

		// 初始化 Tabs 页面。
		$("#tabs").tabs();
	</script>



</body>

</html>